#include "level.h"

#include <SDL/SDL.h>
#include <iostream>

using std::vector;
using std::list;
using std::pair;

Level::Level(Song & song) : displayedDuration(20000), levelPosition(0), song(song), running(true),
	state(PLAYING), life(60), lifeIncrement(3), lifeDecrement(10), lifeMax(100), hitWindow(50)
{
	songIterator = song.obstaclesFrom(0);
}


Level::~Level() {}


void Level::startTimer()
{
	timeOffset = SDL_GetTicks();
}


int Level::getTotalTime()
{
	return levelPosition;
}


unsigned int Level::getElapsedTime()
{
	return levelPosition - previousTime;
}
	

void Level::update()
{
	previousTime = levelPosition;
	levelPosition = SDL_GetTicks() - timeOffset;

	songIterator.setPosition(levelPosition);

	if(state == GAMEOVER) {
		return;
	}

	for(list<pair<Obstacle*,bool> >::iterator it = currentObstacles.begin() ; it != currentObstacles.end() ; ) {
		if(it->first->getTime() + it->first->getDuration() <= levelPosition) {
			if(!it->second) {
				life += lifeIncrement;
				if(life > lifeMax) {
					life = lifeMax;
				}
			}
			it = currentObstacles.erase(it);
		} else {
			++it;
		}
	}

	for(Song::Iterator it = song.obstaclesFrom(levelPosition) ; it != Song::Iterator::end() && it.getPosition() < levelPosition + hitWindow ; ++it) {
		bool found = false;
		for(list<pair<Obstacle*,bool> >::iterator itSearch = currentObstacles.begin() ; itSearch != currentObstacles.end() && !found ; ++itSearch) {
			if(itSearch->first == (*it)) {
				found = true;
			}
		}
		if(!found) {
			currentObstacles.push_back(pair<Obstacle*,bool>(*it, false));
		}
	}
}


void Level::collision(Obstacle * obstacle)
{
	if(state == GAMEOVER) {
		return;
	}

	for(list<pair<Obstacle*,bool> >::iterator it = currentObstacles.begin() ; it != currentObstacles.end() ; ++it ) {
		if(it->first == obstacle && it->second == false) {
			it->second = true;
			life -= lifeDecrement;
			if(life <= 0) {
				state = GAMEOVER;
				life = 0;
			}
		}
	}
}


Song & Level::getSong(){
	return song;
}


ObstaclePosition Level::getObstaclePosition(Obstacle * obstacle)
{
	ObstaclePosition pos;

	switch(obstacle->getType()) {
		case Obstacle::Top:
			pos.x = -1.0f;
			pos.y = 1.0f - obstacle->getSize1() / 100.f;
			pos.width = 2.0f;
			pos.height = obstacle->getSize1() / 100.f;
			break;
		case Obstacle::Bottom:
			pos.x = -1.0f;
			pos.y = -1.0f;
			pos.width = 2.0f;
			pos.height = obstacle->getSize1() / 100.f;
			break;
		case Obstacle::Left:
			pos.x = -1.0f;
			pos.y = -1.0f;
			pos.width = obstacle->getSize1() / 100.f;
			pos.height = 2.0f;
			break;
		case Obstacle::Right:
			pos.x = 1.0f - obstacle->getSize1() / 100.f;
			pos.y = -1.0f;
			pos.width = obstacle->getSize1() / 100.f;
			pos.height = 2.0f;
			break;
	}

	pos.z = (obstacle->getTime() - levelPosition) / 1000.0f;
	pos.depth = obstacle->getDuration() / 1000.0f;

	return pos;
}


void Level::handleEvents()
{
	SDL_Event event;
	while(SDL_PollEvent(&event)) {
		switch(event.type) {
			case SDL_QUIT:
				std::cout << "SDL_QUIT" << std::endl;
				running = false;
				break;
			case SDL_KEYDOWN:
				switch (event.key.keysym.sym) {
					case SDLK_ESCAPE:
						std::cout << "SDLK_ESCAPE" << std::endl;
						running = false;
						break;
					case SDLK_UP:
						break;
					case SDLK_DOWN:
						break;
					case SDLK_LEFT:
						break;
					case SDLK_RIGHT:
						break;
					}
				break;
		}
	}
}


bool Level::shouldRun()
{
	return running || SDL_PeepEvents(NULL,0,SDL_PEEKEVENT,SDL_QUITMASK);
}
